#ifndef AVALON_TASKSIGNALHANDLER_HPP
#define AVALON_TASKSIGNALHANDLER_HPP
#include <boost/noncopyable.hpp>
#include "Avalon/SignalHandling/QueuedSignalHandler.hpp"
#include "Avalon/Threading/Async.hpp"

namespace Avalon {
namespace SignalHandling {

  /*! \class TaskSignalHandler
   *  \brief Allows for the handling of signals in a concurrent task.
   */
  class TaskSignalHandler : private boost::noncopyable {
    public:

      //! Constructs a TaskSignalHandler.
      TaskSignalHandler();

      //! Constructs a TaskSignalHandler.
      /*!
        \param threadPool The ThreadPool to handle the tasks in.
      */
      TaskSignalHandler(Threading::ThreadPool& threadPool);

      ~TaskSignalHandler();

      //! Initializes the TaskSignalHandler.
      /*!
        \param threadPool The ThreadPool to handle the tasks in.
      */
      void Initialize(Threading::ThreadPool& threadPool);

      //! Returns a slot compatible with this signal handler.
      /*!
        \tparam SlotType A function type of the form R (P0, P1, ...)
        \tparam FunctionType The function type compatible with the SlotType.
        \param slot The slot to make compatible with this signal handler.
        \return A slot compatible with this signal handler.
      */
      template<typename SlotType, typename FunctionType>
      typename GetFunctionType<SlotType>::Type GetSlot(
          const FunctionType& slot) {
        return m_queuedSignalHandler.GetSlot<SlotType>(static_cast<SlotType>(
          slot));
      }

    private:
      boost::mutex m_mutex;
      Threading::ThreadPool* m_threadPool;
      QueuedSignalHandler m_queuedSignalHandler;
      boost::function<void ()> m_signalProcessor;
      std::vector<Threading::Async<void>*> m_results;
      bool m_stopping;
      boost::condition_variable m_resultsEmptyCondition;

      void OnSignalsQueued();
      void OnSignalsProcessed(Threading::Async<void>* result);
  };
}
}

#endif // AVALON_TASKSIGNALHANDLER_HPP
